package cn.lym.lucene.quickstart.index;

import java.io.File;
import java.io.FileReader;
import java.io.Reader;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.document.LongField;
import org.apache.lucene.document.StoredField;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;

import cn.lym.lucene.quickstart.util.FileUtil;
import cn.lym.lucene.quickstart.util.StreamUtil;

/**
 * 提供对磁盘文件建立索引的功能
 * 
 * @author liuyimin
 *
 */
public class Indexer {
	/**
	 * Logger对象
	 */
	private static final Logger logger = LogManager.getLogger(Indexer.class);

	/**
	 * 建立索引
	 * 
	 * @param indexDir
	 *            索引保存路径
	 * @param dataDirs
	 *            数据文件路径
	 * @throws Exception
	 */
	public void index(String indexDir, String... dataDirs) throws Exception {
		Directory directory = FSDirectory.open(new File(indexDir));
		IndexWriterConfig config = new IndexWriterConfig(Version.LATEST, new StandardAnalyzer());
		IndexWriter writer = new IndexWriter(directory, config);

		for (String dataDir : dataDirs) {
			index(writer, new File(dataDir));

			writer.commit();
		}

		// 关闭流
		StreamUtil.close(writer, directory);
	}

	/**
	 * 对文件（或目录）建立索引
	 * 
	 * @param writer
	 *            IndexWriter对象
	 * @param file
	 *            文件或目录
	 */
	private void index(IndexWriter writer, File file) {
		if (file.isDirectory()) {// 目录，需要递归建立索引
			File[] subFiles = file.listFiles();
			if (subFiles != null) {
				for (File subFile : subFiles) {
					index(writer, subFile);
				}
			}
		} else if (file.isFile()) {// 文件，对文件建立索引
			if (logger.isDebugEnabled()) {
				logger.debug("indexing file: " + file.getAbsolutePath());
			}

			try {
				Document document = file2Document(file);
				writer.addDocument(document);
			} catch (Exception e) {
				logger.error(
						"An error occurred while adding a document to indexwriter. File: " + file.getAbsolutePath(), e);
			}
		}
	}

	/**
	 * 将文件转为lucene的{@link Document}类型<br/>
	 * 其中包括：
	 * <ul>
	 * <li>pathname：路径名</li>
	 * <li>filename：文件名</li>
	 * <li>size：文件大小（字节）</li>
	 * <li>type：文件类型</li>
	 * <li>content：文件内容（只有明文文件有，判断是否是明文文件：{@link FileUtil#isPlainTextFile(File)}
	 * ）</li>
	 * </ul>
	 * 
	 * @param file
	 * @return
	 */
	private Document file2Document(File file) {
		Document document = new Document();
		document.add(new StringField("filename", file.getName(), Store.YES));
		document.add(new StoredField("pathname", file.getAbsolutePath()));
		document.add(new StringField("type", FileUtil.getFileType(file), Store.YES));
		document.add(new LongField("size", file.length(), Store.YES));
		document.add(new LongField("lastmodified", file.lastModified(), Store.YES));
		if (FileUtil.isPlainTextFile(file)) {// 对明文文件的内容建立索引
			try {
				Reader reader = new FileReader(file);
				document.add(new TextField("content", reader));
			} catch (Exception e) {
				logger.error("An error occurred while indexing " + file.getAbsolutePath(), e);
			}
		}
		return document;
	}
}
